延續先前己建立的學生資料範例,今天加上學生成績。
StudentView.kt
上加上新增及顯示成績畫面vok-orm和許多orm使用方式類似,在這篇文裡不會特別詳細解說,倘若未曾使用過任何jpa、orm,看這篇文章時可先忽略霧裡看花的部份,日後會專篇介紹。
Grade.kt
data class Grade(
override var id: Long? = null,
var student_id: Long? = null,
val description: String? = null,
var english: Double? = null,
var math: Double? = null,
var mandarin:Double? = null,
var pe: Double? = null
): KEntity<Long>{
companion object: Dao<Grade, Long>(Grade::class.java)
val student: Student?
get() = student_id?.let { Student.getById(student_id!!)} ?: null
}
V02__CreateGrade.sql
(命名規格請參考d04)create TABLE Grade(
id bigint auto_increment PRIMARY KEY,
mandarin DOUBLE NOT NULL,
description VARCHAR(50) NOT NULL,
english DOUBLE NOT NULL,
math DOUBLE NOT NULL,
pe DOUBLE NOT NULL,
student_id bigint not null REFERENCES Student(id)
)
在這張資料表裡除了自動編號的 primary key id
外,還有一個 foreign key student_id
,由於使用 H2 database,所以程式重啟時,兩個.sql都會執行。倘若使用的是其他資料庫如 MySQL,則 FlyWay 只會執行尚未被執行的.sql。
StudentView.kt
:
:
private lateinit var student: Student
private lateinit var gradeDiv: Div
private val gradeBinder = beanValidationBinder<Grade>()
private lateinit var addGradeButton: Button
private val root = ui {
verticalLayout {
:
:
:
h2("成績")
gradeDiv = div()
p("新增成績")
textField("學期"){
bind(gradeBinder).bind(Grade::description)
placeholder = "第一學期"
}
numberField("國文"){
bind(gradeBinder).bind(Grade::mandarin)
}
numberField("英文"){
bind(gradeBinder).bind(Grade::english)
}
numberField("數學"){
bind(gradeBinder).bind(Grade::math)
}
numberField("體育"){
bind(gradeBinder).bind(Grade::pe)
}
addGradeButton = button("新增"){
onLeftClick { addGrade() }
}
editLink = routerLink(VaadinIcon.EDIT,null)
}
}
gradeDiv = div()
表示在畫面上新增空的DIV區塊
private fun addGrade() {
val grade = Grade()
if (gradeBinder.validate().isOk && gradeBinder.writeBeanIfValid(grade)){
grade.student_id = student.id
grade.save()
refreshGrades()
gradeBinder.readBean(Grade())
}
}
private fun refreshGrades() {
gradeDiv.removeAll()
student.grades.fetch().forEach {
gradeDiv.html("<p>" +
"<strong>學期:</strong>${it.description} " +
"<strong>國文:</strong>${it.mandarin} " +
"<strong>英文:</strong>${it.english} " +
"<strong>數學:</strong>${it.math} " +
"<strong>體育:</strong>${it.pe}" +
"</p>")
}
}
清空DIV區塊,查詢這位學生所有成績後再逐一顯示,這裡插入div區塊使用的是html,在VoK裡,對dom的操作也極為容易。
Student.kt
val grades : DataLoader<Grade>
get() = Grade.dataLoader.withFilter {
Grade::student_id eq id
}
當有人讀取grads時,下條件查詢資料來源 Grade
Grade.kt
加上欄位驗證資訊 @field:NotNull
var student_id: Long? = null,
@field:NotNull
@field:Size(min = 4)
var description: String? = null,
@field:NotNull
@field:DecimalMin(value = "0.0")
@field:DecimalMax(value = "100.0")
var english: Double? = null,
:
:
(略)
執行結果 :
本日Source Code已上傳 GitHub